// SPA_Lexical.h :	Declaration of lexical tokens, grammar and function prototypes for SPA_Lexical.cpp
// Author: Heng Belson
//
#ifndef SPA_LEXICAL_H
#define SPA_LEXICAL_H

#include "../SPA_Data_Types.h"
#include <queue>
#include <boost/xpressive/xpressive.hpp>

/***************************************/
// Forward Declarations
/***************************************************************************************************************************/
struct	Block;
class	CompareStartPos;
/***************************************************************************************************************************/

/***************************************/
// Type Definitions
/***************************************************************************************************************************/
typedef boost::xpressive::sregex											TOKEN;
typedef boost::xpressive::sregex											GRAMMAR;
typedef boost::xpressive::sregex											LEXICAL;
typedef boost::xpressive::smatch											MATCHED;
typedef std::string															TOKEN_KEY;
typedef std::queue<STRING>													SQUEUE;
typedef std::priority_queue<Block, std::vector<Block>, CompareStartPos>		BCONTAINER;
/***************************************************************************************************************************/

class SPA_Lexical {

public :
	enum CONSTRUCT_TYPE { CONSTRUCT_Procedure, CONSTRUCT_Statement_List, CONSTRUCT_Statement, CONSTRUCT_Expression, CONSTRUCT_Operands };

	/***************************************/
	// Constructor
	/***************************************************************************************************************************/
	SPA_Lexical();
	/***************************************************************************************************************************/

	/***************************************/
	// Main Components
	/***************************************************************************************************************************/
	void			scanner(STRING fileName);
	BOOLEAN			match(STRING line, LEXICAL lex);
	void			analyze(CONSTRUCT_TYPE constructType);
	/***************************************************************************************************************************/

	/******************************/
	// Tokens and Grammars
	/***************************************************************************************************************************/
	TOKEN			T_Name, T_Integer;
	TOKEN			T_Proc_Name, T_Var_Name, T_Const_Value;
	TOKEN_KEY		TK_Procedure, TK_Call, TK_While, TK_If, TK_Then, TK_Else;

	GRAMMAR			G_Program, G_Procedure;
	GRAMMAR			G_StmtLst, G_Stmt;
	GRAMMAR			G_Call, G_While, G_If, G_Assign;
	GRAMMAR			G_Then, G_Else;
	GRAMMAR			G_Group, G_Factor, G_Term, G_Term2, G_Expression, G_Expression2;
	/***************************************************************************************************************************/

	/******************************/
	// Get Methods
	/***************************************************************************************************************************/
	STRING			getNextProcedure();
	STRING			getProcName();
	STRING			getProcBody();
	COLLECTION		getStmtLstBlock();
	INTEGER			getTotalProcedures();
	STATEMENT_TYPE	getStmtType();
	STRING			getCall();
	STRING			getWhileCondition();
	STRING			getWhileBody();
	STRING			getIfCondition();
	STRING			getIfThenPart();
	STRING			getIfElsePart();
	STRING			getAssignLeftVar();
	STRING			getOriginalExpr();
	STRING			getAssignExpr();
	/***************************************************************************************************************************/

	BOOLEAN			isReducible(STRING expression);
	BOOLEAN			isOperator(char c);

private :
	enum MATCH_TYPE { MATCH_Procedure, MATCH_Statement_List };

	/******************************/
	// Do Methods
	/***************************************************************************************************************************/
	BOOLEAN			doProcedure();
	BOOLEAN			doStatementList();
	BOOLEAN			doStatement();
	BOOLEAN			doExpression();
	BOOLEAN			doCheck(BOOLEAN forContainer, STRING line);
	BOOLEAN			doIfContainer(STRING line);
	BOOLEAN			doWhileContainer(STRING line);
	BOOLEAN			doCall(STRING line);
	BOOLEAN			doWhile(STRING line);
	BOOLEAN			doIf(STRING line);
	BOOLEAN			doAssign(STRING line);
	/***************************************************************************************************************************/

	/******************************/
	// Support Methods
	/***************************************************************************************************************************/
	BOOLEAN			manualMatch(STRING line, MATCH_TYPE matchType);
	BOOLEAN			isValidCall(COLLECTION procList, STRING procName);
	BOOLEAN			hasProcedure(COLLECTION procList, STRING procName);
	STRING			evaluateVarName(STRING line);
	STRING			getMatchedResult();
	INTEGER			getOperatorPrecedence(const char c);
	/***************************************************************************************************************************/

	/******************************/
	// Set Methods
	/***************************************************************************************************************************/
	void			setProcName(STRING name);
	void			setProcBody(STRING body);
	void			setStmtLstBlock(COLLECTION stmtLst);
	void			setStmtType(STATEMENT_TYPE stmtType);
	void			setCall(STRING procName);
	void			setWhileCondition(STRING condition);
	void			setWhileBody(STRING body);
	void			setIfCondition(STRING condition);
	void			setIfThenPart(STRING body);
	void			setIfElsePart(STRING body);
	void			setAssignLeftVar(STRING leftVar);
	void			setOriginalExpr(STRING expr);
	void			setAssignExpr(STRING expr);
	/***************************************************************************************************************************/
};
#endif